﻿using System;
using System.Collections.Specialized;
using System.IO;
using System.Net;
using System.Text;
using System.Threading;

namespace WebAssertTestLibrary.Core
{
    public class CssValidator : W3CValidator
    {
        public CssValidator()
        {
            ValidatorUrl = "http://jigsaw.w3.org/css-validator/validator";
        }

        static readonly AutoResetEvent CssBlocker = new AutoResetEvent(true);
        protected override EventWaitHandle Blocker { get { return CssBlocker; } }

        public W3CValidityCheckResult IsValidCss(string css)
        {
            using (var wc = GetWebClient())
            {
                return IsValid(wc, css);
            }
        }

        protected override NameValueCollection PrepareW3CRequest(string payload)
        {
            return new NameValueCollection
                {
                    {"text", payload},
                    {"profile", "css21"},
                    {"usermedium", "all"},
                    {"warning", "1"},
                    {"lang", "en"}
                };
        }

        protected override string SendW3CRequest(WebHeaderCollection w3cResponseHeaders, WebClient wc, string url, NameValueCollection values, EventWaitHandle blocker)
        {
            var request = (HttpWebRequest)WebRequest.Create(url);
            var boundary = "-------------------------45962402127348";
            request.ContentType = string.Format("multipart/form-data; boundary={0}", boundary);
            request.Method = "POST";
            request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
            request.Headers.Add("Accept-Encoding", "gzip,deflate");
            request.Headers.Add("Accept-Language", "en-gb,en;q=0.5");
            request.Headers.Add("Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7");
            request.Headers.Add("Cache-Control", "max-age=0");
            request.Expect = string.Empty;
            request.KeepAlive = true;
            request.Pipelined = false;

            var contents = new StringBuilder();
            boundary = "--" + boundary;
            contents.Append(boundary);

            const string mask = "Content-Disposition: form-data; name=\"{0}\"";
            foreach (var key in values.AllKeys)
            {
                contents.AppendLine();
                var header = String.Format(mask, key);
                var value = values[key];
                contents.AppendLine(header);
                contents.AppendLine();
                contents.AppendLine(value);
                contents.Append(boundary);
            }
            contents.AppendLine("--");
            var payload = contents.ToString();
            var bytes = Encoding.UTF8.GetBytes(payload);
            request.ContentLength = bytes.Length;

            try
            {
                blocker.WaitOne();
                using (var stream = request.GetRequestStream())
                {
                    stream.Write(bytes, 0, bytes.Length);
                }

                using (var response = (HttpWebResponse)request.GetResponse())
                using (var stream = response.GetResponseStream())
                using (var reader = new StreamReader(stream))
                {
                    w3cResponseHeaders.Add(response.Headers);
                    return reader.ReadToEnd();
                }
            }
            finally
            {
                ThreadPool.QueueUserWorkItem(ResetW3CBlocker, blocker); // Reset on background thread
            }
        }
    }
}